/**
 *  Copyright (C) 2007 Marcos Diez < marcos AT unitron.com.br >
 *  Copyright (C) 2005 PGT-Linux.org http://www.pgt-linux.org
 *  Author: vandorpe Olivier <vandorpeo@pgt-linux.org>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <syslog.h>
#include <string.h>
#include <stdio.h>
#include <pthread.h>

#include "fifoApi.h"

#include "usbb2k-api.h"
#include "usbb2k-main.h"
#include "usbServer.h"
#include "cmdServer.h"
#include "usbTalker.h"
#include "yealinkProtocol.h"
/* USB server thread */

void *usbServer(yealinkDevice_t *yealinkDevice) {
	// int client;
	int keypress_state, dialtone_state=OFF;
	int last_handset_state_flag, handset_state_flag, keypress_state_flag,
			key_code;
	int last_pstn_ringing_state_flag, pstn_ringing_state_flag;
	int ringing_mode_flag;

	syslog(LOG_INFO,"USB server started");

	/* init */
	ringing_mode_flag=ERR;
	handset_state_flag=ERR;
	last_pstn_ringing_state_flag=ERR;
	pstn_ringing_state_flag=ERR;

	/* start usb loop */

	usb_loop=ON;
	check_handset_keypress_pstnring(yealinkDevice->dev_h, &handset_state,
			&keypress_state, &pstn_ringing_state_flag);

	keypress_state_flag= keypress_state;

	while (usb_loop==ON) {

		if (usbContinuousBusErrorCounter > MAX_CONTINUOUS_USB_ERROS) {
			usb_loop=OFF;
			cmdServer_loop=OFF;
			fifoWrite(yealinkDevice, "%s", FIFO_SAY_DEVICE_REMOVED);
			continue;
		}

		check_handset_keypress_pstnring(yealinkDevice->dev_h, &handset_state,
				&keypress_state, &pstn_ringing_state_flag);
		/* check HANDSET and notify client */

		if (pstn_ringing_state_flag != last_pstn_ringing_state_flag) {
			last_pstn_ringing_state_flag = pstn_ringing_state_flag;
			if (pstn_ringing_state_flag == ON) {
				fifoWrite(yealinkDevice, "%s", FIFO_SAY_PSTN_RING);
			}
		}

		if (handset_state_flag!=handset_state) {
			last_handset_state_flag=handset_state_flag;
			handset_state_flag=handset_state;

			if (handset_state == ON) {
				fifoWrite(yealinkDevice, "%s", FIFO_SAY_HANDSET_ON);
			} else {
				fifoWrite(yealinkDevice, "%s", FIFO_SAY_HANDSET_OFF);
			}

			if (ringing_state==ON) {
				ringing_state=OFF;
				ringing_mode=OFF;
				ringing_mode_flag=OFF;
				usbb2k_ring(yealinkDevice->dev_h, OFF);
			}
		}

		if (handset_state==OFF) {
			/* set RING */
			if (ringing_state==ON || ringing_mode_flag==ON) {
				if (ringing_mode_flag!=ringing_mode) {
					ringing_mode_flag=ringing_mode;
					if (ringing_mode_flag==ON) {
						usbb2k_ring(yealinkDevice->dev_h, ON);
					} else {
						usbb2k_ring(yealinkDevice->dev_h, OFF);
						// --- added by chris at lunarflow.com 05/08/2008 ---
						if (ringing_sendcid==ON) {
							ringing_sendcid=OFF;
							fifoWrite(yealinkDevice, "SENDCID\n");
						}
					}
				}
			}
		}

		if (handset_state==ON || pstn_and_usb_joined==1) {
			/* check KEYPRESS */
			if (keypress_state != ERR) {
				if (keypress_state_flag!=keypress_state) {
					keypress_state_flag=keypress_state;
					key_code=usbb2k_get_key(yealinkDevice->dev_h,
							keypress_state);
					if (key_code!=ERR) {
						fifoWrite(yealinkDevice, FIFO_SAY_KEY_NUM, key_code);
					}
				}
			}
		}

		//added by simon dible 08-01-07
		//dial tone functions
		// modified by dmitry romashko 2007-09-06
		/* set DIALTONE */
		if (dialtone != dialtone_state) {
			if (dialtone == ON) {
				if (ON==usbb2k_tone(yealinkDevice->dev_h,ON))
					dialtone_state = ON;
			} else {
				if (OFF==usbb2k_tone(yealinkDevice->dev_h,OFF))
					dialtone_state = OFF;
			}
		}

		usleep(25000);
	}

	/* cleanup */
	hangup_pstn(yealinkDevice->dev_h);
	usbb2k_switch_mode(yealinkDevice->dev_h, PSTN_MODE);

	/* that does not work and lock the daemon */
	/* by the time we get here, the "client" socket is already closed */
	/*   sprintf(msg,"USB DISCONNECT\n"); */
	/*   syslog(LOG_INFO,"MMMM 111"); */
	/*   if (write(client,msg,strlen(msg)) == -1){ */
	/*     syslog(LOG_ERR,"error writing socket %s", msg); */
	/*   } */

	/* Stop Ringing LOOP */
	ringing_state=OFF;
	/* Stop ring */

	usbb2k_ring(yealinkDevice->dev_h, OFF);

	syslog(LOG_INFO,"USB server shutdown");
	//this function is not mandatory to be called and valgrind says it leaks. so we don't call it
	// pthread_exit(NULL);
	return 0;
}
